import HttpBase from './httpBase';
import {
  AUTH_WHITE_LIST,
  XHR_ERROR_WHITE_LIST,
  XHR_DATA_SUCCESS_CODE,
  XHR_DATA_ERROR_CODE,
  XHR_TOKEN_EXPIRES_CODE
} from './conf';
import { Modal, message } from 'ant-design-vue';
import router, { resetRouter } from '../router/index';

/**
 * 节流
 * @param {*} fn
 * @param {*} wait
 * @returns
 */
const throttle = (fn, wait) => {
  let previous = 0;
  return function() {
    let now = new Date().getTime();
    if (now - previous > wait) {
      fn.apply(this, arguments);
      previous = now;
    }
  };
};

/**
 * 信息提示，使用节流函数
 */
const messageFn = throttle(msg => {
  message.error(msg);
}, 1000);

class Http extends HttpBase {
  constructor() {
    super();
  }

  /**
   * ajax request
   */
  request(url, method, params) {
    return new Promise((resolve, reject) => {
      const http_request = new XMLHttpRequest();
      http_request.onreadystatechange = function() {
        const _data = JSON.parse(http_request.responseText);
        if (http_request.readyState == 4 && http_request.status == 200) {
          resolve(_data);
        } else {
          reject(_data);
        }
      };
      http_request.open(method, url, true);

      // 参数处理
      const paramsHandel = () => {
        if (method === 'GET') {
          http_request.setRequestHeader('Content-Type', 'application/json;charset=UTF-8');
          return params;
        }
        // http_request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        let data = new FormData();
        for (var i in params) {
          data.append(i, params[i]);
        }
        return data;
      };

      http_request.send(paramsHandel());
    });
  }

  /**
   * get 请求
   * @param {*} url 请求URL
   * @param {*} params 请求参数
   * @param {*} headers 自定义请求头{}
   * @param {*} proxyUrl 请求的proxy前缀，默认为环境变量
   * @returns Promise
   */
  get(url, params, headers = {}, proxyUrl = null) {
    return new Promise((resolve, reject) => {
      this._get(url, params, headers, proxyUrl)
        .then(res => {
          this.successHandel(url, res);
          resolve(res);
        })
        .catch(err => {
          this.errorHandel(url, err);
          reject(err);
        });
    });
  }

  /**
   * post 表单 请求
   * @param {*} url 请求URL
   * @param {*} params 请求参数
   * @param {*} headers 自定义请求头{}
   * @param {*} proxyUrl 请求的proxy前缀，默认为环境变量
   * @returns Promise
   */
  post(url, params, headers = {}, proxyUrl = null) {
    return new Promise((resolve, reject) => {
      this._post(url, params, headers, proxyUrl)
        .then(res => {
          this.successHandel(url, res);
          resolve(res);
        })
        .catch(err => {
          this.errorHandel(url, err);
          reject(err);
        });
    });
  }

  /**
   * post JSON 提交 请求
   * @param {*} url 请求URL
   * @param {*} params 请求参数
   * @param {*} headers 自定义请求头{}
   * @param {*} proxyUrl 请求的proxy前缀，默认为环境变量
   * @returns Promise
   */
  postJSON(url, params, headers = {}, proxyUrl = null) {
    return new Promise((resolve, reject) => {
      this._postJSON(url, params, headers, proxyUrl)
        .then(res => {
          this.successHandel(url, res);
          resolve(res);
        })
        .catch(err => {
          this.errorHandel(url, err);
          reject(err);
        });
    });
  }

  /**
   * post File 文件上传 请求
   * @param {*} url 请求URL
   * @param {*} params 请求参数
   * @param {*} headers 自定义请求头{}
   * @param {*} proxyUrl 请求的proxy前缀，默认为环境变量
   * @returns Promise
   */
  postFile(url, params, headers = {}, proxyUrl = null) {
    return new Promise((resolve, reject) => {
      this._postFile(url, params, headers, proxyUrl)
        .then(res => {
          this.successHandel(url, res);
          resolve(res);
        })
        .catch(err => {
          this.errorHandel(url, err);
          reject(err);
        });
    });
  }

  /**
   * Download File 请求
   * @param {*} url
   * @param {*} params
   * @param {*} headers
   * @param {*} proxyUrl
   * @returns
   */
  downFile(url, params, headers = {}, proxyUrl = null) {
    return new Promise((resolve, reject) => {
      this._downFile(url, params, headers, proxyUrl)
        .then(res => {
          // this.successHandel(url, res);
          let fileName = res['headers']['content-disposition'].replace('attachment;filename=', '');
          fileName = decodeURIComponent(fileName);
          if (!res) {
            reject(res);
            return;
          }
          if (res['status'] === 200) {
            let linkUrl = window.URL.createObjectURL(new Blob([res.data])),
              link = document.createElement('a');
            link.style.display = 'none';
            link.href = linkUrl;
            link.setAttribute('download', fileName);
            document.body.appendChild(link);
            link.click();
            // 然后移除
            document.body.removeChild(link);
          }
          resolve(res);
        })
        .catch(err => {
          this.errorHandel(url, err);
          reject(err);
        });
    });
  }

  /**
   * 2次确认
   */
  comfirm(title, content, callbackFn) {
    Modal.confirm({
      title,
      content,
      onOk() {
        return new Promise((resolve, reject) => {
          callbackFn(resolve, reject);
        });
      },
      onCancel() {}
    });
  }

  /**
   * xhr 成功处理
   * @param {*} url
   * @param {*} res
   */
  successHandel(url, res) {
    const {
      data: { code, message }
    } = res;
    // 过期code
    if (code === XHR_TOKEN_EXPIRES_CODE) {
      this.userClear();
      return;
    }
    // unsuccess
    if (code === XHR_DATA_ERROR_CODE && !XHR_ERROR_WHITE_LIST.includes(url)) {
      messageFn(message);
      return;
    }
  }

  /**
   * xhr 异常处理
   * @param {*} url
   * @param {*} err
   * @returns
   */
  errorHandel(url, err) {
    const { status, data } = err.response;
    let { message, error } = data;
    message = message ? message : error ? error : '服务器异常';
    switch (status) {
      // 用户未登录或token失效
      case 401:
        if (message === 'email or password error') {
          messageFn(message);
        } else {
          this.userClear();
        }
        break;
      case 403:
        messageFn(message);
        break;
      case 404:
        messageFn(message);
        break;
      case 405:
        messageFn(message);
        break;
      case 500:
        if (message === 'Token失效，请重新登录') {
          // 鉴权页面直接跳转到登陆页
          if (!AUTH_WHITE_LIST.includes(url)) {
            this.userClear();
          }
          return;
        }
        messageFn(message);
        break;
      default:
        break;
    }
  }

  /**
   * token 过期 用户注销
   */
  userClear() {
    // 删除token
    this._deleteToken();
    // 重置路由
    resetRouter();
    // 跳转登陆页
    router.push({ name: 'login' });
  }
}

// 实例化
const $http = new Http();

export default Object.seal($http);
